﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NMbsDuplex.TCPServerX.Deamon
{
    using System.Net.Sockets;
    using NMbsDuplex.ProtocalBuffer.Bifrost;

    /// 小于等于32kb的文件 直接使用Socket工具函数SendFile()完成
    public enum BFileTransMethod
    {
        Tiny5, SendOnce, Slice5, Big5,
    }

    public static class TCPExtension
    {
        internal const int T1stPacLen = 9;
        internal const int PACKSIZE = short.MaxValue / 8;
        internal static Encoding blockCoder = Encoding.UTF8;

        // Socket扩展 发送文本
        public static int QosSend(this Socket refSock, string CombinMsg)
        {
            byte[] buffer = blockCoder.GetBytes(CombinMsg);
            var N29 = buffer.Length;
            var times = 0;
            while (N29 > 0)
            {
                int N92 = refSock.Send(buffer);
                if(N92 > 0)
                {
                    N29 -= N92;
                    times++;
                }
            }
            return N29;
        }

        /* Socket扩展 接受文本 解析编码为运行时传入 */
        public static string QosRecv(
            this Socket refSock, ref int N)
        {
            /* Tips : 有进有出用ref 只出不进用out */
            byte[] buffer = new byte[PACKSIZE];
            N = refSock.Receive(buffer,0,PACKSIZE,SocketFlags.None);
            string receivingMsg = blockCoder.GetString(buffer, 0, N);

            return receivingMsg;
        }

        /// <summary>
        /// TCP封包函数 一次读取一个文件全部内容到List<byte>序列
        /// </summary>
        /// <param name="refSock">文件描述符</param>
        /// <param name="fileUrl">文件本地路径</param>
        /// <param name="mode">传输模式</param>
        /// <returns> 流量标识 </returns>
        public static long TCPPacking(this Socket refSock,
            string fileUrl, BFileTransMethod mode)
        {
            switch (mode)
            {
                default:
                case BFileTransMethod.SendOnce:
                    {
                        // 0.调用协议进行任意流的封包
                        var rawData = HolySword.TCPPacking(fileUrl) as List<byte>;
                        byte[] h1 = new byte[T1stPacLen];
                        byte[] hN = new byte[rawData.Count() - T1stPacLen];
                        rawData.CopyTo(0, h1, 0, T1stPacLen);
                        rawData.RemoveRange(0, T1stPacLen);
                        rawData.CopyTo(hN);
                        rawData.Clear();
                        // 1.TCP封包传输应该先传输首包 
                        int n31 = refSock.Send(h1, 0, h1.Length, SocketFlags.None);

                        /* 2.V1版本使用`进程内同步`传输 */
                        int page, rest;
                        rest = hN.Length % PACKSIZE;
                        page = hN.Length / PACKSIZE + ((rest == 0) ? 0 : 1);
                        int N51 = 0, times = 0;
                        while (N51 < hN.Length)
                        {
                            int pos = times * PACKSIZE;
                            int end = (times == page - 1) ? rest : PACKSIZE;
                            int N15 = refSock.Send(hN, pos, end, SocketFlags.None);
                            if (N15 > 0)
                            {
                                times++;
                                N51 += N15;
                            }
                            Console.WriteLine("发送 TCP分片儿大小[{1}:{0}kb]", N15, times);
                        }
                        var QosInfo = HolySword.YouTube(N51);
                        var transInfo = string.Format("本次传输一共{3}.进行{0}次,分片大小{1:F}kb,尾片长度{2:F}kb", page, PACKSIZE / 1024.00F, rest / 1024.0F, QosInfo);
                        Console.WriteLine(transInfo);
                        break;
                    }
                case BFileTransMethod.Tiny5:
                case BFileTransMethod.Slice5:
                case BFileTransMethod.Big5:
                    break;
            }
            return -1;
        }
    }
}
